<?php

/**
 * Ignus Framework
 *
 * @author Sergey Palyanov <sergey.palyanov@gmail.com>
 * @link http://code.google.com/p/ignus-php/
 * @license http://apache.org/licenses/LICENSE-2.0
 * @package Ignus
 * @subpackage App
 * @since 0.1
 */

namespace Ignus;

/**
 * @package Ignus
 * @subpackage App
 * @since 0.1
 */
abstract class Controller
{
    /**
     * @var Router Router object
     * @since 0.4
     */
    private $router;

    /**
     * @var array Request parameters
     */
    protected $params;

    /**
     * @var \Ignus\Model Model object
     */
    protected $model = null;

    /**
     * @param Router $router
     * @param array $params Request parameters
     */
    public function __construct(Router $router, array $params)
    {
        $this->router = $router;
        $this->params = $params;
    }

    /**
     * @return \Ignus\Model
     */
    public function model()
    {
        if ($this->model != null)
            return $this->model;

        $modelClass = 'Models\\' . $this->router->getController();
        class_exists($modelClass, true);
        return $this->model = new $modelClass();
    }

    /**
     * Renders the default template for controller
     * @param array $vars Template variables
     * @return void
     */
    protected final function render(array $vars = array())
    {
        $controller = str_replace('\\', DIRECTORY_SEPARATOR, $this->router->getController());
        $template = $controller . DIRECTORY_SEPARATOR . $this->router->getAction() . '.html';

        $this->renderTemplate($template, $vars);
    }

    /**
     * Renders and outputs template with specified name
     * @param string $template Path to template
     * @param array $vars Template variables
     * @return void
     */
    protected final function renderTemplate($template, array $vars = array())
    {
        $view = new View($template);
        $view->display($vars);
        exit();
    }

    /**
     * Renders AJAX response
     * @param array $object Object to JSONize
     * @return void
     * @throws RuntimeException if headers already sent
     * @since 0.4
     */
    protected final function renderJson(array $object)
    {
        $this->setContentType('application/json');
        echo json_encode($object);
        exit();
    }

    /**
     * Performs redirect to specified controller action
     * @param string $controller Controller class name
     * @param string $action Action method name
     * @param array $params Action parameters
     * @return void
     * @since 0.4
     */
    protected final function redirect($controller, $action, array $params = array())
    {
        $path = App::getRouter()->assemble($controller, $action, $params);
        $this->redirectUrl($path);
    }

    /**
     * Redirects client to specified url
     * @param string $url Url or relative path to redirect to
     * @return void
     * @throws RuntimeException if headers already sent
     * @since 0.4
     */
    protected final function redirectUrl($url)
    {
        $this->checkHeaders();
        header("Location: $url");
        exit();
    }

    /**
     * Set contents type of response
     * @param string $type content type without encoding (which is always utf-8)
     * @return void
     * @throws RuntimeException if headers already sent
     * @since 0.4.4
     */
    protected final function setContentType($type)
    {
        $this->checkHeaders();
        header("Content-Type: $type; charset=utf-8", true);
    }

    /**
     * Throws exception if HTTP headers already sent
     * @throws RuntimeException
     * @return void
     * @since 0.4
     */
    private function checkHeaders()
    {
        if (headers_sent($file, $line))
            throw new \RuntimeException("Can't redirect, headers already sent by $file:$line");
    }
}
